import { useState, useCallback, useEffect, useRef } from "react";
import { Skeleton, Alert, Collapse } from "antd";
import { throttle as _throttle, debounce as _debounce, get } from "lodash";
import classnames from "classnames";
import ReactResizeDetector from "react-resize-detector";

import type { ContentItem } from "./index";
import { renderStateCache, heightCache, useResize } from "./utils";

import styles from "./index.less";

const { Panel } = Collapse
export interface ItemRenderProps extends ContentItem {
  params?: any;
  cacheKey: string;
  threshold: number;
  lazyload: boolean;
  isLast: boolean;
  isFirst: boolean;
  defaultHeight: number;
  defaultMinHeight: number;
  defaultRecordRenderingStatus: boolean;
  component: any;
  wrapperContainerRef: {
    current: Element;
  };
}

const INIT_OBJECT = {};
const MARGIN = 5;
const SKELETON_LENGTH = 40;

function noop() {
}

/**
 * 上下文锚点项渲染组件
 */
const ItemRender = (props: ItemRenderProps) => {
  const {
    id,
    title,
    component: Component,
    content,
    height,
    minHeight: customMinHeight,
    maxHeight,
    recordRenderingStatus,
    params = INIT_OBJECT,
    cacheKey,
    threshold,
    lazyload,
    resizable = true,
    defaultHeight,
    defaultMinHeight,
    defaultRecordRenderingStatus,
    autoHeight = false,
    wrapperContainerRef,
    ...restMenuParams //包含上下文菜单定义时的参数
  } = props;

  const wrapperRef = useRef<HTMLDivElement>(null);
  const [isRender, setIsRender] = useState(() => {
    if (!lazyload) return true;
    if (
      typeof recordRenderingStatus === "undefined" &&
      !defaultRecordRenderingStatus
    ) {
      return false;
    }
    if (typeof recordRenderingStatus === "boolean" && !recordRenderingStatus) {
      return false;
    }
    return renderStateCache.get(`${cacheKey}-${id}`);
  });

  const [currentHeight, setCurrentHeight] = useState(() => heightCache.get(`${cacheKey}-${id}`) || height || defaultHeight);
  const minHeight = customMinHeight || defaultMinHeight;

  const calculateIsInScreen = useCallback(
    _debounce(() => {
      const wrapperContainer = wrapperContainerRef.current;
      const screenTop = wrapperContainer?.scrollTop || 0;
      const screenBottom = screenTop + (wrapperContainer?.clientHeight || 0);
      const dom = wrapperRef.current;
      const domOffsetTop = dom?.offsetTop || 0;
      const domOffsetBottom = domOffsetTop + (dom?.offsetHeight || 0);

      // 条件1, 渲染块的头部距离视窗底部在阀值内
      const condition1 =
        domOffsetTop >= screenTop && domOffsetTop <= screenBottom + threshold;
      // 条件2, 渲染块的底部距离视窗顶部在阀值内
      const condition2 =
        domOffsetBottom >= screenTop - threshold &&
        domOffsetBottom <= screenBottom;
      // 条件3, 渲染块在视窗中已经完全占满或已完全超出屏幕高度的场景
      const condition3 =
        domOffsetTop <= screenTop && domOffsetBottom >= screenBottom;
      if (condition1 || condition2 || condition3) {
        renderStateCache.set(`${cacheKey}-${id}`, true);
        setIsRender(true);
      }
    }, 300),
    []
  );

  const onScroll = useCallback(() => {
    calculateIsInScreen();
  }, []);

  const throttleSetCurrentHeight = useCallback(
    _throttle(setCurrentHeight, 16),
    []
  );

  const onResize = useCallback(
    _debounce((width, height) => setCurrentHeight(height), 200),
    []
  );

  const { onMouseDown, resizing, resizingHeihgt, maskPosition } = useResize({
    height: currentHeight,
    minHeight,
    maxHeight,
    onSizeChange: throttleSetCurrentHeight,
  });

  useEffect(() => {
    !isRender && calculateIsInScreen();
  }, []);

  useEffect(() => {
    if (!isRender) {
      wrapperContainerRef.current?.addEventListener("scroll", onScroll);
    }
    return () => {
      wrapperContainerRef.current?.removeEventListener("scroll", onScroll);
    };
  }, [isRender]);

  const renderContent = () => {
    if (isRender) {
      return (
        <>
          {autoHeight ? (
            <ReactResizeDetector
              handleWidth
              handleHeight
              onResize={onResize}
            >
              {content || (
                <Component
                  {...params}
                  {...restMenuParams}
                  height={currentHeight}
                  title={title}
                />
              )}
            </ReactResizeDetector>
          ) : (
            content || (
              <Component
                {...params}
                {...restMenuParams}
                height={currentHeight}
                title={title}
              />
            )
          )}
        </>
      )
    } else {
      return (<div
        className={styles["skeleton-wrapper"]}
        style={{ height: currentHeight }}
      >
        <Skeleton
          loading
          active
          paragraph={{
            rows: SKELETON_LENGTH,
            width: new Array(SKELETON_LENGTH)
              .fill(400)
              .map((item, index) => item + Math.random() * 300),
          }}
        />
      </div>);
    }
  };



  const ItemRenderContent = () => (
    <div
      ref={wrapperRef}
      style={{ paddingTop: MARGIN }}
      className={classnames(styles["render-item-wrapper"])}
    >
      <div
        style={{ height: currentHeight }}
        className={classnames(styles["rnd"], {
          [styles["rnd-resizing"]]: resizing,
        })}
      >
        <div className={styles["render-item-content"]}>
          {renderContent()}
        </div>
        {resizable && !autoHeight && (
          <div className={styles["resize-wrapper"]} onMouseDown={onMouseDown}>
            <div
              className={classnames(styles["resize-handle"], {
                [styles["resize-handle__down"]]: currentHeight <= minHeight,
                [styles["resize-handle__up"]]: maxHeight && currentHeight >= (maxHeight as number),
              })}
            />
          </div>
        )}
        {resizing && (
          <div className={styles["resize-mask"]} style={maskPosition} />
        )}
        <span
          className={classnames(styles["rnd-resizing__tip"], {
            [styles["rnd-resizing__tip__show"]]: resizing,
          })}
        >
          <span
            style={{ display: resizingHeihgt <= minHeight ? "inline" : "none" }}
          >
            {tr("已是最小高度")}
          </span>
          <span
            style={{
              display:
                maxHeight && resizingHeihgt >= (maxHeight as number)
                  ? "inline"
                  : "none",
            }}
          >
            {tr("已是最大高度")}
          </span>
        </span>
      </div>
    </div>
  );

  const showCollapseList = ['PCR', 'IC']

  if (!content && !Component) {
    return (
      <div id={id}>
        <Alert message={tr("没有配置对应的content或者component")} />
      </div>
    );
  }

  if (showCollapseList.includes(get(params, 'templateKey', '').split('_')[0])) {
    return (
      <div id={id}>
        <Collapse defaultActiveKey={id} openAnimation={{
            animation: {},
            component: 'span',
            componentProps: {},
            transitionEnter: false,
            transitionLeave: false,
            transitionAppear: false,
            onEnd: noop,
            onEnter: noop,
            onLeave: noop,
            onAppear: noop,
          }}>
          <Panel forceRender header={<div style={{ display: 'inline-block', height: '14px', fontWeight:'bold' }}>{title}</div>} key={id}>
            { ItemRenderContent()}
          </Panel>
        </Collapse>
      </div>
    )
  }

  return (
    <div id={id}>
      {ItemRenderContent()}
    </div>
  )
};

export default ItemRender
